package com.sudoku.screen;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator;
import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator.FreeTypeFontParameter;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.sudoku.Sudoku;
import com.sudoku.board.GameHandler;
import com.sudoku.input.InputHandler;
import com.sudoku.observer.Event;
import com.sudoku.observer.Observer;
import com.sudoku.observer.Subject;
import com.sudoku.sound.AudioManager;
import com.sudoku.utility.Constants;
import com.sudoku.utility.Locator;

public class GameScreen implements Screen, Constants, Observer {

	private Box2DDebugRenderer renderer;
	private OrthographicCamera camera;
	private BitmapFont smallFont, pencilFont;
	private SpriteBatch gameSprites;
	private Subject subject;
	private Rectangle viewport;
	private GameHandler gameHandler;
	private Sudoku game;

	public GameScreen(OrthographicCamera camera, AudioManager audioManager, Subject subject, Sudoku game) {
		this.camera = camera;
		this.subject = subject;
		this.game = game;

		gameSprites = new SpriteBatch();

		subject.addObserver(this);

		// fonts
		FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal(FONT));
		FreeTypeFontParameter param = new FreeTypeFontParameter();
		param.size = (int) (58);
		smallFont = generator.generateFont(param);
		smallFont.setColor(Color.BLACK);
		param.size = (int) (26);
		pencilFont = generator.generateFont(param);
		pencilFont.setColor(Color.BLACK);
		generator.dispose();

		gameHandler = new GameHandler(subject, 0);

		renderer = new Box2DDebugRenderer();
		// input
		Locator.getInputMultiplexer().addProcessor(new InputHandler(this));

	}

	@Override
	public void render(float delta) {
		gameSprites.setTransformMatrix(Locator.getCamera().view);
		gameSprites.setProjectionMatrix(Locator.getCamera().projection);
		// Entire game speed will affect everything

		camera.update();
		Gdx.gl.glClearColor(1f, 1f, 1f, 1);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

		gameHandler.render(gameSprites, smallFont, pencilFont);

		// update all entities
		update(delta);

		Locator.getEvents().update(delta);
		
		//update ad timer...show an ad after this many seconds
		Locator.adTimer+=delta;

	}

	/**
	 * Update all entities, music, background
	 * 
	 * @param delta
	 */
	public void update(float delta) {
		// update game entities
		gameHandler.update(delta);
	}

	public void findTile(float x, float y) {
		if (x >= Locator.getViewport().getLeftGutterWidth() + Locator.BOARD_START_POSITION) {
			gameHandler.changeTileColor(x, y);
		}
	}

	public void selectTile(float x, float y) {
		if (x >= Locator.xScale * BOARD_START_POSITION) {
			gameHandler.selectTile();
		}
	}

	/**
	 * Called when screen is resized
	 */
	@Override
	public void resize(int width, int height) {
		// calculate new viewport
		// sprite scales used for proportions
		Locator.getViewport().update(width, height);
		Locator.resize();
	}

	/**
	 * Called when the game screen appears
	 */
	@Override
	public void show() {
		Gdx.input.setInputProcessor(Locator.getInputMultiplexer());
		resumeGame();
	}

	/**
	 * Called when game screen goes away
	 */
	@Override
	public void hide() {
	}

	@Override
	public void pause() {
	}

	@Override
	public void resume() {
	}

	public void resumeGame() {
	}

	@Override
	public void dispose() {

	}

	/**
	 * This class is an observer so onNotify handles the events
	 */
	@Override
	public void onNotify(Event event) {
		//System.out.println(event.name());
		switch (event) {
		case EVENT_MENU_TO_GAME:

			break;
		case EVENT_GAME_TO_MENU:
			gotoMenu();
			break;
		default:
			break;
		}
	}

	public void gotoMenu() {
		MenuScreen next = game.getMenuScreen();
		game.setScreen(next);
	}

	public Rectangle getViewport() {
		return viewport;
	}

	public void setViewport(Rectangle viewport) {
		this.viewport = viewport;
	}

	public Subject getSubject() {
		return subject;
	}

	public Box2DDebugRenderer getRenderer() {
		return renderer;
	}

	public void setTileData(char character) {
		gameHandler.setTileData(character);

	}

	public void undo() {
		gameHandler.undo();

	}

	public void startGame() {
		Gdx.input.setCatchBackKey(true);
		gameHandler.startGame();

	}

	public void writeSave(Preferences prefs) {
		if (Locator.gameInProgress) {
			gameHandler.writeSave(prefs);
		}
		prefs.putBoolean("gameInProgress", Locator.gameInProgress);

	}

	public void readSave(Preferences prefs) {
		gameHandler.readSave(prefs);

	}

}
